#pragma once
#include <iostream>
#include <string>
#include <deque>
#include <thread>
#include <mutex>
#include <type_traits>
#include <typeinfo>
#include <atomic>
typedef std::lock_guard<std::mutex> locker_t;

//this class is thread salf
template <typename OBJ>
class ObjPool{
public:
    ObjPool(uint32_t pool_size):pool_size_(pool_size){
	}

    ~ObjPool(){
		exit_.store(true);
    }

    void pushObj(OBJ* obj){
        assert(obj);
        locker_t lock(mtx_);
		if (que_obj_.size() < pool_size_)
			que_obj_.push_back(obj);
		else
			delete obj;
        
    }

    OBJ* getObj(){
        locker_t lock(mtx_);
        if (!que_obj_.empty()) {
            OBJ* ret_obj = que_obj_.front();
            que_obj_.pop_front();
            return ret_obj;
        }
        return nullptr;
    }

	void  freePool()
	{
		locker_t lock(mtx_);
		for (auto it : que_obj_) {
			auto obj = dynamic_cast<OBJ*>(it);
			assert(obj);
			delete obj;
		}
	}

private:
	uint32_t         pool_size_;
	AtmBool          exit_;
    std::mutex       mtx_;
    std::deque<OBJ*> que_obj_;

};

